package org.onion.pattern.event.spring.autoconfigure;

import org.apache.commons.lang3.ObjectUtils;
import org.onion.pattern.event.io.EventDeserializer;
import org.onion.pattern.event.outbox.DefaultEventOutbox;
import org.onion.pattern.event.outbox.OutboxDeliveryExecutor;
import org.onion.pattern.event.outbox.OutboxEventStorage;
import org.onion.pattern.event.outbox.OutboxEventConverter;
import org.onion.pattern.event.outbox.config.EventOutboxConfig;
import org.onion.pattern.event.publish.DefaultEventChannelPublisher;
import org.onion.pattern.event.publish.EventChannelPublisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@ComponentScan({"org.onion.pattern.event.spring"})
@ConditionalOnMissingBean(OnionPatternEventAutoConfigure.class)
public class OnionPatternEventAutoConfigure {

    @Autowired
    private OutboxEventStorage      outBoxEventStorage;
    @Autowired
    private OutboxDeliveryExecutor  deliveryExecutor;
    @Autowired(required = false)
    private List<EventDeserializer> eventDeserializers;
    @Autowired(required = false)
    private List<OutboxEventConverter> converters;


    @ConfigurationProperties("onion-pattern.event.outbox")
    @Bean
    public EventOutboxConfig eventOutBoxConfig() {
        return new EventOutboxConfig();
    }

    @Bean
    @ConditionalOnMissingBean
    public EventChannelPublisher defaultEventChannelPublisher() {
        return new DefaultEventChannelPublisher();
    }


    @Bean(initMethod = "init")
    @ConditionalOnMissingBean
    public DefaultEventOutbox eventOutBox() {
        List<EventDeserializer> deserializers = ObjectUtils.defaultIfNull(eventDeserializers, Collections.emptyList());
        deserializers = deserializers.stream()
                .sorted(Comparator.comparingInt(EventDeserializer::getOrder))
                .collect(Collectors.toList());

        DefaultEventOutbox defaultEventOutBox = new DefaultEventOutbox();
        defaultEventOutBox.setStorage(outBoxEventStorage);
        defaultEventOutBox.setDeliveryExecutor(deliveryExecutor);
        defaultEventOutBox.setEventDeserializers(deserializers);
        defaultEventOutBox.setConverters(ObjectUtils.defaultIfNull(converters, Collections.emptyList()));
        return defaultEventOutBox;
    }


//    @Bean
//    @ConditionalOnMissingBean
//    public DomainEventConsumeLogger domainEventConsumeLogger() {
//        return new JdbcDomainEventConsumeLogger();
//    }


//    @Bean
//    @ConditionalOnMissingBean
//    public DomainEventIdempotentChecker domainEventIdempotentChecker() {
//        return new JdbcDomainEventIdempotentChecker();
//    }


//    @Bean
//    @ConditionalOnMissingBean
//    public JdbcEventStorage jdbcEventStorage(){
//        return new JdbcEventStorage();
//    }


//    @Bean
//    @ConditionalOnMissingBean
//    @Primary
//    public ExternalizedDomainEventHandler outboxExternalizedDomainEventHandler(){
//        return new OutboxExternalizedEventHandler();
//    }


//    @Bean
//    @ConditionalOnMissingBean
//    public JdbcDomainEventTrackerRepository publishedEventTrackerStore() {
//        return new JdbcDomainEventTrackerRepository();
//    }


//    @Bean
//    public RocketEventListenerFactory externalEventListenerFactory() {
//        return new RocketEventListenerFactory();
//    }


}
